/**
 * 
 */
package profiler.exec;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import profiler.SingletonTimer;

public class MutableExecution extends AbstractExecution implements Execution {

    private final Map<Long, MutableExecution> children = new HashMap<Long, MutableExecution>();

    private long executions;

    private long totalTime;

    private long minTime = Long.MAX_VALUE;

    private long maxTime = Long.MIN_VALUE;

    public MutableExecution(Execution parent, long key) {
        super(parent, key);
    }

    public MutableExecution(long key) {
        super(key);
    }

    public Collection<? extends Execution> children() {
        return children.values();
    }

    public long numberOfExecutions() {
        return executions;
    }

    public long totalTimeNano() {
        return totalTime;
    }

    public long minTime() {
        return minTime;
    }

    public long maxTime() {
        return maxTime;
    }

    public void addExecution(long nano) {
        this.executions++;
        this.totalTime += nano;
        minTime = Math.min(minTime, nano);
        maxTime = Math.max(maxTime, nano);
    }

    public MutableExecution addChild(String identification) {
        long key = SingletonTimer.getOrCreateKey(identification);
        MutableExecution execution = this.children.get(key);
        if (execution == null) {
            execution = new MutableExecution(this, key);
            this.children.put(key, execution);
        }
        return execution;
    }

    private long lastStarted;

    public void start() {
        this.lastStarted = System.nanoTime();
    }

    public void stop() {
        this.addExecution(System.nanoTime() - lastStarted);
    }

    /**
     * {@inheritDoc}
     * 
     * @see java.lang.Object#toString()
     */

    @Override
    public String toString() {
        return "{ \"nam\":\"" + getMethodName()
                + "\",  \"exs\":" + executions + ", \"max\":" + maxTime + ", \"min\":" + minTime
                + ", \"tot\":" + totalTime + ", \"avg\":" + avgTime() + ", \"chld\":" + children.values() + "}\n";
    }

}